package com.hmc.modules.sjfx.controller.sjfx;

import com.hmc.common.utils.Result;
import com.hmc.modules.material.service.tqmtqp.Tqmtqp1Service;
import com.hmc.modules.sjfx.dto.sjfx.*;
import com.hmc.modules.sjfx.service.tmm0001.Tmm0001Service;
import com.hmc.modules.sjfx.service.tpmmmba.TpmmmbaService;
import com.hmc.modules.sjfx.service.tpmmmda.TpmmmdaService;
import com.hmc.modules.sjfx.service.tpmmmea.TpmmmeaService;
import com.hmc.modules.sjfx.service.tqmtqapsxx.Tqmtqa1Service;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.*;

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;

/**
 * 抗拉强度[钢管-焊缝-主材]正态拟合曲线
 *
 * @author hmc wengxiulinluman@qq.com
 * @since 3.0 2024-01-05
 */

@AllArgsConstructor
@RestController
@RequestMapping("sjfx/klqd")
@Tag(name = "抗拉强度[钢管-焊缝-主材]正态拟合曲线")
public class KlqdController {

    @Autowired
    private TpmmmbaService tpmmmbaService;

    @Autowired
    private TpmmmdaService tpmmmdaService;

    @Autowired
    private TpmmmeaService tpmmmeaService;

    @Autowired
    private Tmm0001Service tmm0001Service;

    @Autowired
    private Tqmtqp1Service tqmtqp1Service;

    @Autowired
    private Tqmtqa1Service tqmtqa1Service;

    /**
     * 抗拉强度屈服强度[钢管-焊缝]正态拟合曲线
     */
    @GetMapping("gghf")
    @Operation(summary = "抗拉强度[钢管-焊缝]正态拟合曲线")
    public Result<GgHf1DTO> getGgHf(){
        HashMap<String, String> wglhAndSphMap = getWglhAndSph();
        HashMap<String, List<LashenDTO>> laShenMap = tqmtqp1Service.queryTqmtqp1BySampleLotNo();

        // 创建抗拉强度平均值，标准差，最大值统计对象
        DescriptiveStatistics klqd = new DescriptiveStatistics();
        // 创建屈服强度平均值，标准差，最大值统计对象
        DescriptiveStatistics qfqd = new DescriptiveStatistics();



//        List<GghfKlqdDTO> gghfklqd = new ArrayList<>();

        List<Double> ys = new ArrayList<>();
        List<Double> ts = new ArrayList<>();

        GghfKlqdDTO gghfKlqdDTO = new GghfKlqdDTO();
        //遍历拉伸 map
        Iterator<Map.Entry<String, List<LashenDTO>>> iterator = laShenMap.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<String, List<LashenDTO>> next = iterator.next();
            String key = next.getKey();
            List<LashenDTO> value = next.getValue();
            if(value.size() > 0){
                String originHeatNo = value.get(0).getOriginHeatNo();
                //根据炉号获取原材料的试批号
                String rawSampleLotNo = wglhAndSphMap.get(originHeatNo);
                if(laShenMap.containsKey(rawSampleLotNo)){
                    List<LashenDTO> rawLashenEntityList = laShenMap.get(rawSampleLotNo);
                    //将钢管和原材料的拉伸性能放到一起
                    for(LashenDTO lashenDTO : value){
                        klqd.addValue(lashenDTO.getTs());
                        qfqd.addValue(lashenDTO.getYs());
                        ys.add(Double.valueOf(lashenDTO.getYs()));
                        ts.add(Double.valueOf(lashenDTO.getTs()));
                    }
                }
            }
        }

        // 获取抗拉强度的平均值
        double klqdMeanmean = klqd.getMean();
        // 获取抗拉强度的标准差
        double klqdStandardDeviation = klqd.getStandardDeviation();
        // 获取抗拉强度的最大值
        double klqdMax = klqd.getMax();
        // 获取抗拉强度的最小值
        double klqdMin = klqd.getMin();

        // 获取屈服强度的平均值
        double qfqdMean = qfqd.getMean();
        // 获取屈服强度的标准差
        double qfqdStandardDeviation = qfqd.getStandardDeviation();
        // 获取屈服强度的最大值
        double qfqdMax = qfqd.getMax();
        // 获取屈服强度的最小值
        double qfqdMin = qfqd.getMin();

        // 创建正态分布对象
        Double y=0.0;  //期望值，标准正态分布y=0
        Double z=1.0;  //方差，标准正态分布z=1
        NormalDistribution normalDistributioin = new NormalDistribution(y,z);

        Collections.sort(ys);
        Collections.sort(ts);

        GgHf1DTO ggHf1DTO = new GgHf1DTO(ys,ts,klqdMeanmean,klqdStandardDeviation,klqdMax,klqdMin,qfqdMean,qfqdStandardDeviation,qfqdMax,qfqdMin);

        return new Result<GgHf1DTO>().ok(ggHf1DTO);
    }

    /**
     * 抗拉强度屈服强度[钢管-焊缝]正态拟合曲线
     */
    @GetMapping("klqdztnh")
    @Operation(summary = "抗拉强度[钢管-焊缝]正态拟合曲线")
    public Result<GgHfDTO> getGgHfNormalFitztnh(){
        HashMap<String, String> wglhAndSphMap = getWglhAndSph();
        HashMap<String, List<LashenDTO>> laShenMap = tqmtqp1Service.queryTqmtqp1BySampleLotNo();

        // 创建抗拉强度平均值，标准差，最大值统计对象
        DescriptiveStatistics klqd = new DescriptiveStatistics();
        // 创建屈服强度平均值，标准差，最大值统计对象
        DescriptiveStatistics qfqd = new DescriptiveStatistics();

        List<Double> ys = new ArrayList<>();
        List<Double> ts = new ArrayList<>();

        GghfKlqdDTO gghfKlqdDTO = new GghfKlqdDTO();
        //遍历拉伸 map
        Iterator<Map.Entry<String, List<LashenDTO>>> iterator = laShenMap.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<String, List<LashenDTO>> next = iterator.next();
            String key = next.getKey();
            List<LashenDTO> value = next.getValue();
            if(value.size() > 0){
                String originHeatNo = value.get(0).getOriginHeatNo();
                //根据炉号获取原材料的试批号
                String rawSampleLotNo = wglhAndSphMap.get(originHeatNo);
                if(laShenMap.containsKey(rawSampleLotNo)){
                    List<LashenDTO> rawLashenEntityList = laShenMap.get(rawSampleLotNo);
                    //将钢管和原材料的拉伸性能放到一起
                    for(LashenDTO lashenDTO : value){
                        klqd.addValue(lashenDTO.getTs());
                        qfqd.addValue(lashenDTO.getYs());
                        ys.add(Double.valueOf(lashenDTO.getYs()));
                        ts.add(Double.valueOf(lashenDTO.getTs()));
                    }
                }
            }
        }

        // 获取抗拉强度的平均值
        double klqdMeanmean = klqd.getMean();
        // 获取抗拉强度的标准差
        double klqdStandardDeviation = klqd.getStandardDeviation();
        // 获取抗拉强度的最大值
        double klqdMax = klqd.getMax();
        // 获取抗拉强度的最小值
        double klqdMin = klqd.getMin();

        // 获取屈服强度的平均值
        double qfqdMean = qfqd.getMean();
        // 获取屈服强度的标准差
        double qfqdStandardDeviation = qfqd.getStandardDeviation();
        // 获取屈服强度的最大值
        double qfqdMax = qfqd.getMax();
        // 获取屈服强度的最小值
        double qfqdMin = qfqd.getMin();

        // 创建正态分布对象
        Double y=0.0;  //期望值，标准正态分布y=0
        Double z=1.0;  //方差，标准正态分布z=1
        NormalDistribution normalDistributioin = new NormalDistribution(y,z);


        // 创建抗拉强度正态分布概率
        List<Double> klqdztfb = new ArrayList<>();
        // 创建屈服强度正态分布概率
        List<Double> qfqdztfb = new ArrayList<>();
        Collections.sort(ys);
        Collections.sort(ts);

        HashMap<Double, Integer> ysmap = new HashMap<>();
        HashMap<Double, Integer> tsmap = new HashMap<>();

        for (Double d:ys) {
            if (ysmap.containsKey(d)) {
                Integer integer = ysmap.get(d);
                Integer yst = integer+1;
                ysmap.put(d, yst);
            }else {
                ysmap.put(d, 1);
            }
            klqdztfb.add(normalDistributioin.cumulativeProbability(d));
        }
        for (Double d:ts) {
            if (tsmap.containsKey(d)) {
                Integer integer = tsmap.get(d);
                Integer tst = integer+1;
                tsmap.put(d, tst);
            }else {
                tsmap.put(d, 1);
            }
            qfqdztfb.add(normalDistributioin.cumulativeProbability(d));
        }

        List<Double> yskeylist = new ArrayList<>();
        for (Map.Entry<Double, Integer> entry:ysmap.entrySet()) {
            yskeylist.add(entry.getKey());
        }
        List<Integer> ysvlist = new ArrayList<>();
        for (Map.Entry<Double, Integer> entry:ysmap.entrySet()) {
            ysvlist.add(entry.getValue());
        }

        List<Double> tskeylist = new ArrayList<>();
        for (Map.Entry<Double, Integer> entry:tsmap.entrySet()) {
            tskeylist.add(entry.getKey());
        }
        List<Integer> tsvlist = new ArrayList<>();
        for (Map.Entry<Double, Integer> entry:tsmap.entrySet()) {
            tsvlist.add(entry.getValue());
        }

//        GgHfDTO ggHfDTO = new GgHfDTO(yskeylist, ysvlist, tskeylist, tsvlist, klqdMeanmean, klqdStandardDeviation, klqdMax, klqdMin, qfqdMean, qfqdStandardDeviation, qfqdMax, qfqdMin);
        GgHfDTO ggHfDTO = new GgHfDTO(yskeylist, ysvlist, tskeylist, tsvlist, klqdMeanmean, klqdStandardDeviation, klqdMax, klqdMin, qfqdMean, qfqdStandardDeviation, qfqdMax, qfqdMin,klqdztfb,qfqdztfb);

        return new Result<GgHfDTO>().ok(ggHfDTO);
    }

    /**
     * 抗拉强度屈服强度[钢管-焊缝]正态拟合曲线
     */
    @GetMapping("gghfnormal")
    @Operation(summary = "抗拉强度[钢管-焊缝]正态拟合曲线")
    public Result<GgHf2DTO> getGgHfNormalFit(){
        HashMap<String, String> wglhAndSphMap = getWglhAndSph();
        HashMap<String, List<LashenDTO>> laShenMap = tqmtqp1Service.queryTqmtqp1BySampleLotNo();
        // 创建抗拉强度平均值，标准差，最大值统计对象
        DescriptiveStatistics klqd = new DescriptiveStatistics();
        // 创建屈服强度平均值，标准差，最大值统计对象
        DescriptiveStatistics qfqd = new DescriptiveStatistics();



//        List<GghfKlqdDTO> gghfklqd = new ArrayList<>();

        List<Double> ys = new ArrayList<>();
        List<Double> ts = new ArrayList<>();

        GghfKlqdDTO gghfKlqdDTO = new GghfKlqdDTO();
        //遍历拉伸 map
        Iterator<Map.Entry<String, List<LashenDTO>>> iterator = laShenMap.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<String, List<LashenDTO>> next = iterator.next();
            String key = next.getKey();
            List<LashenDTO> value = next.getValue();
            if(value.size() > 0){
                String originHeatNo = value.get(0).getOriginHeatNo();
                //根据炉号获取原材料的试批号
                String rawSampleLotNo = wglhAndSphMap.get(originHeatNo);
                if(laShenMap.containsKey(rawSampleLotNo)){
                    List<LashenDTO> rawLashenEntityList = laShenMap.get(rawSampleLotNo);
                    //将钢管和原材料的拉伸性能放到一起
                    for(LashenDTO lashenDTO : value){
                        klqd.addValue(lashenDTO.getTs());
                        qfqd.addValue(lashenDTO.getYs());
                        ys.add(Double.valueOf(lashenDTO.getYs()));
                        ts.add(Double.valueOf(lashenDTO.getTs()));
//                        gghfKlqdDTO.setSampleLotNo(lashenDTO.getSampleLotNo());
//                        gghfKlqdDTO.setYs(BigDecimal.valueOf(lashenDTO.getYs()));
//                        gghfKlqdDTO.setTs(BigDecimal.valueOf(lashenDTO.getTs()));
//                        gghfklqd.add(gghfKlqdDTO);
//                        System.out.println(lashenDTO);
//                        if (!"P".equals(lashenDTO.getSamplePosCode())) {
//                            klqd.addValue(lashenDTO.getTs());
//                            qfqd.addValue(lashenDTO.getYs());
//                            ys.add(Double.valueOf(lashenDTO.getYs()));
//                            ts.add(Double.valueOf(lashenDTO.getTs()));
//                        }
                    }
                }
            }
        }

        // 获取抗拉强度的平均值
        double klqdMeanmean = klqd.getMean();
        // 获取抗拉强度的标准差
        double klqdStandardDeviation = klqd.getStandardDeviation();
        // 获取抗拉强度的最大值
        double klqdMax = klqd.getMax();
        // 获取抗拉强度的最小值
        double klqdMin = klqd.getMin();

        // 获取屈服强度的平均值
        double qfqdMean = qfqd.getMean();
        // 获取屈服强度的标准差
        double qfqdStandardDeviation = qfqd.getStandardDeviation();
        // 获取屈服强度的最大值
        double qfqdMax = qfqd.getMax();
        // 获取屈服强度的最小值
        double qfqdMin = qfqd.getMin();

        // 创建正态分布对象
        Double y=0.0;  //期望值，标准正态分布y=0
        Double z=1.0;  //方差，标准正态分布z=1
        NormalDistribution normalDistributioin = new NormalDistribution(y,z);


        // 创建抗拉强度正态分布概率
        List<Double> klqdztfb = new ArrayList<>();
        // 创建屈服强度正态分布概率
        List<Double> qfqdztfb = new ArrayList<>();
        Collections.sort(ys);
        Collections.sort(ts);

        HashMap<Double, Integer> ysmap = new HashMap<>();
        HashMap<Double, Integer> tsmap = new HashMap<>();

        for (Double d:ys) {
            if (ysmap.containsKey(d)) {
                Integer integer = ysmap.get(d);
                Integer yst = integer+1;
                ysmap.put(d, yst);
            }else {
                ysmap.put(d, 1);
            }
            klqdztfb.add(normalDistributioin.cumulativeProbability(d));
        }
        for (Double d:ts) {
            if (tsmap.containsKey(d)) {
                Integer integer = tsmap.get(d);
                Integer tst = integer+1;
                tsmap.put(d, tst);
            }else {
                tsmap.put(d, 1);
            }
            qfqdztfb.add(normalDistributioin.cumulativeProbability(d));
        }

        // 创建抗拉强度平均值，标准差，最大值统计对象
        DescriptiveStatistics ysklqd = new DescriptiveStatistics();
        // 创建屈服强度平均值，标准差，最大值统计对象
        DescriptiveStatistics tsqfqd = new DescriptiveStatistics();

        List<Double> yskeylist = new ArrayList<>();
        for (Map.Entry<Double, Integer> entry:ysmap.entrySet()) {
            yskeylist.add(entry.getKey());
        }
        List<Integer> ysvlist = new ArrayList<>();
        for (Map.Entry<Double, Integer> entry:ysmap.entrySet()) {
            ysklqd.addValue(entry.getValue());
            ysvlist.add(entry.getValue());
        }

        List<Double> tskeylist = new ArrayList<>();
        for (Map.Entry<Double, Integer> entry:tsmap.entrySet()) {
            tskeylist.add(entry.getKey());
        }
        List<Integer> tsvlist = new ArrayList<>();
        for (Map.Entry<Double, Integer> entry:tsmap.entrySet()) {
            tsqfqd.addValue(entry.getValue());
            tsvlist.add(entry.getValue());
        }


        // 获取抗拉强度的平均值
        double ysklqdMeanmean = ysklqd.getMean();
        // 获取抗拉强度的标准差
        double ysklqdStandardDeviation = ysklqd.getStandardDeviation();
        // 获取抗拉强度的最大值
        double ysklqdMax = ysklqd.getMax();
        // 获取抗拉强度的最小值
        double ysklqdMin = ysklqd.getMin();
        // 获取屈服强度的平均值
        double tsqfqdMean = tsqfqd.getMean();
        // 获取屈服强度的标准差
        double tsqfqdStandardDeviation = tsqfqd.getStandardDeviation();
        // 获取屈服强度的最大值
        double tsqfqdMax = tsqfqd.getMax();
        // 获取屈服强度的最小值
        double tsqfqdMin = tsqfqd.getMin();

        // 创建ys正态分布对象
        NormalDistribution ysnorm =  new NormalDistribution(ysklqdMeanmean,ysklqdStandardDeviation);
        NormalDistribution tsnorm =  new NormalDistribution(tsqfqdMean,tsqfqdStandardDeviation);

        // 创建抗拉强度正态分布概率
        List<Double> ysvztfb = new ArrayList<>();
        // 创建屈服强度正态分布概率
        List<Double> tsvztfb = new ArrayList<>();
        for (Integer d:ysvlist) {
            ysvztfb.add(ysnorm.cumulativeProbability(d));
        }
        for (Integer d:tsvlist) {
            tsvztfb.add(tsnorm.cumulativeProbability(d));
        }

        GgHf2DTO ggHfNormalFitDTO = new GgHf2DTO(ys,ts,ysmap,tsmap,klqdMeanmean,klqdStandardDeviation,klqdMax,klqdMin,qfqdMean,qfqdStandardDeviation,qfqdMax,qfqdMin,ysvztfb,tsvztfb,yskeylist,ysvlist,tskeylist,tsvlist);

        return new Result<GgHf2DTO>().ok(ggHfNormalFitDTO);
    }

    /**
     * 整合炉号和原材料的试批号的关系
     * @return
     */
    public HashMap<String, String> getWglhAndSph(){
        HashMap<String, String> wglhAndSphMap = new HashMap<>();

        // 缓存直缝炉号和原材料的试批号的关系
        List<SphAndWglhDTO> sphAndWglhBAS = tpmmmbaService.queryTpmmmbaBySphAndWglh();

        for (SphAndWglhDTO sphAndWglhDTO:sphAndWglhBAS) {
            wglhAndSphMap.put(sphAndWglhDTO.getOriginHeatNo(),sphAndWglhDTO.getSampleLotNo());
            if (!wglhAndSphMap.containsKey(sphAndWglhDTO.getOriginHeatNo())){
                wglhAndSphMap.put(sphAndWglhDTO.getOriginHeatNo(),sphAndWglhDTO.getSampleLotNo());
            }
        }

        // 缓存螺旋炉号和原材料的试批号的关系
        List<SphAndWglhDTO> sphAndWglhDAS = tpmmmdaService.queryTpmmmdaBySphAndWglhDA();
        for (SphAndWglhDTO sphAndWglhDTO:sphAndWglhDAS) {
            wglhAndSphMap.put(sphAndWglhDTO.getOriginHeatNo(),sphAndWglhDTO.getSampleLotNo());
            if (!wglhAndSphMap.containsKey(sphAndWglhDTO.getOriginHeatNo())){
                wglhAndSphMap.put(sphAndWglhDTO.getOriginHeatNo(),sphAndWglhDTO.getSampleLotNo());
            }
        }

        // 缓存螺旋炉号和原材料的试批号的关系
        List<SphAndWglhDTO> sphAndWglhEAS = tpmmmeaService.queryTpmmmbaBySphAndWglhEA();
        for (SphAndWglhDTO sphAndWglhDTO:sphAndWglhEAS) {
            wglhAndSphMap.put(sphAndWglhDTO.getOriginHeatNo(),sphAndWglhDTO.getSampleLotNo());
            if (!wglhAndSphMap.containsKey(sphAndWglhDTO.getOriginHeatNo())){
                wglhAndSphMap.put(sphAndWglhDTO.getOriginHeatNo(),sphAndWglhDTO.getSampleLotNo());
            }
        }

        return wglhAndSphMap;
    }

    /**
     * 管号和供应商的关联关系
     * @return
     */
    public HashMap<String, String> getGhAndSupplier() {
        // 创建一个用于存储管号和供应商关联关系的哈希映射
        HashMap<String, String> ghAndSupplierMap = new HashMap<>();

        // 查询销售订单子项和供应商的关联关系，并将其缓存到ghAndSupplierMap中
        // 获取销售订单子项和供应商的对应关系列表
        List<SaleOrderSupplierDTO> saleOrderSupplierDTOS = tmm0001Service.querySaleOrderSubAndSupplier();

        // 遍历对应关系列表
        for (SaleOrderSupplierDTO saleOrderSupplierDTO : saleOrderSupplierDTOS) {
            // 将销售订单子项和供应商的对应关系存储到ghAndSupplierMap中
            ghAndSupplierMap.put(saleOrderSupplierDTO.getSaleOrderSubNo(), saleOrderSupplierDTO.getSupplierName());

            // 如果ghAndSupplierMap中没有该销售订单子项的键，则再次将其销售订单子项和供应商的对应关系存储到ghAndSupplierMap中
            if (!ghAndSupplierMap.containsKey(saleOrderSupplierDTO.getSaleOrderSubNo())) {
                ghAndSupplierMap.put(saleOrderSupplierDTO.getSaleOrderSubNo(), saleOrderSupplierDTO.getSupplierName());
            }
        }

        // 返回存储管号和供应商关联关系的哈希映射ghAndSupplierMap
        return ghAndSupplierMap;
    }

}
